package cn.sc.summer.gateway.filter;

import cn.hutool.core.collection.CollUtil;
import cn.sc.summer.constant.model.Result;
import cn.sc.summer.constant.token.AuthProperties;
import cn.sc.summer.constant.token.TokenConstant;
import cn.sc.summer.constant.util.MatchUtil;
import cn.sc.summer.redis.util.RedisHelper;
import cn.sc.summer.token.constant.APIConstant;
import cn.sc.summer.token.po.UserDetailX;
import cn.sc.summer.token.util.UserUtil;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;

import java.util.List;
import java.util.stream.Collectors;

/**
 * 类名：接口权限处理类
 *
 * @author a-xin
 * @date 2023/12/7 17:27
 */
@Slf4j
public class ApiAuthFilter implements WebFilter {

    private final AuthProperties authProperties;

    public ApiAuthFilter(AuthProperties authProperties) {
        this.authProperties = authProperties;
    }

    @Override
    public @NotNull Mono<Void> filter(ServerWebExchange exchange, @NotNull WebFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();
        String path = request.getPath().value();

        log.info("-> Verify the permissions of the interface: {}", path);
        if (MatchUtil.anyMatchValue(path, authProperties.getAuthIgnore())
                || MatchUtil.anyMatchValue(path, APIConstant.SWAGGER_SOURCE)) {
            return chain.filter(exchange);
        }

        String token = request.getHeaders().getFirst(TokenConstant.ACCESS_TOKEN);
        UserDetailX loginUser = UserUtil.getLoginUser(token);

        List<String> userApiAuth = RedisHelper.lGetAll(TokenConstant.USER_API + loginUser.getUserId())
                .stream().map(String::valueOf).collect(Collectors.toList());
        if (CollUtil.isEmpty(userApiAuth) || !userApiAuth.contains(path)) {
            response.setStatusCode(HttpStatus.FORBIDDEN);
            DataBuffer buffer = response.bufferFactory().wrap(JSON.toJSONString(Result.fail("Sorry, you don't have access to this api！")).getBytes());
            log.error("==> {} , Sorry, you don't have access to this api！", path);
            return response.writeWith(Mono.just(buffer));
        }

        return chain.filter(exchange);
    }

}
